package com.jg.visitor.service.impl;

import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jg.visitor.GlobalConst;
import com.jg.visitor.annotation.LoginCheck;
import com.jg.visitor.common.bean.*;
import com.jg.visitor.common.utils.*;
import com.jg.visitor.config.autoconfiguration.caffeinecache.service.CacheService;
import com.jg.visitor.config.exception.BaseException;
import com.jg.visitor.config.exception.JgException;
import com.jg.visitor.controller.dto.UserDTO;
import com.jg.visitor.controller.dto.UserDetailDTO;
import com.jg.visitor.controller.vo.*;
import com.jg.visitor.domain.*;
import com.jg.visitor.listener.BatchUploadUserExcelListener;
import com.jg.visitor.mapper.LogRecordMapper;
import com.jg.visitor.mapper.UserMapper;
import com.jg.visitor.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author 陈前进
*/
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private LogRecordService logRecordService;
    @Resource
    private LogRecordMapper logRecordMapper;
    @Resource
    private JsonService jsonService;
    @Resource
    private AppConfigs appConfigs;
    @Resource
    private CacheService cacheService;
    @Resource
    private VisitorInfoService visitorInfoService;
    @Resource
    private UserMapper userMapper;
    @Resource
    private VisitorApplyRecordService visitorApplyRecordService;
    @Resource
    private GlobalConfigService globalConfigService;

    /**
     * 记录读取excel存在问题的记录
     */
    private static final List<UploadUserBeanInfo> SINGLE_REQUEST_DATA = new Vector<>();
    private static final Integer RESPONSE_STATUS_SUCCESS = 200;
    private static final String ACCESS_TOKEN_KEY = "access_token";
    private static final Long SUPPER_ADMIN_PID = 0L;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDTO login(UserLoginVO userVO) {
        //通过账号密码查询到用户
        User userInfo = checkAndGetUser(userVO);

        //如果管理员或者审核员第一次登录，则获取openid绑定到用户上,否则直接取数据库的openid
        if(userInfo.getOpenId() == null){
            String openId = LoginHelper.getLoginVisitorOpenId();
            userInfo.setOpenId(openId);
            userInfo.setGmtModified(DateTimeUtil.getTimeNow());
            userInfo.updateById();
        }

        //创建登录信息
        UserDTO dto = buildUserDTO(userInfo);

        //记录此次登录信息
        LogRecord logRecord = new LogRecord();
        logRecord.setLogHost(LoginHelper.getLoginHost());
        logRecord.setLogTime(DateTimeUtil.getTimeNow());
        logRecord.setUserId(userInfo.getId());
        logRecord.setLogIp(LoginHelper.getLoginIp());
        logRecordService.save(logRecord);

        //缓存设置已登录用户
        LoginHelper.setLoginUser(dto);

        return dto;
    }

    @Override
    public UserDTO wxLogin(String jsCode) {
        //非pro环境取测试openId
        String openId = null;

        try{
            openId = getOpenIdByJsCode(jsCode);
        }catch (Exception e){
            log.error("getOpenIdByJsCode error",e);
        }

        if(StringUtils.isEmpty(openId)){
            if(GlobalConst.ENVIRONMENT_PRO.equals(appConfigs.getEnvironment())){
                throw new BaseException(-1,"获取openid异常！");
            }
            openId = GlobalConst.TEST_OPEN_ID;
        }

        //组装访客信息DTO
        return getUserDTObyOpenId(openId);
    }

    @Override
    public UserDTO getUserDTObyOpenId(String openId){
        //判断有没有该openId对应的访客，没有则入库,只做openId关联
        VisitorInfo visitorInfo = visitorInfoService.getOne(new QueryWrapper<VisitorInfo>().eq("open_id", openId));
        if(visitorInfo == null){
            visitorInfo = new VisitorInfo();
            visitorInfo.setGmtModified(DateTimeUtil.getTimeNow());
            visitorInfo.setGmtCreate(DateTimeUtil.getTimeNow());
            visitorInfo.setOpenId(openId);
            visitorInfo.insert();
        }

        //组装访客信息DTO,存入缓存
        UserDTO userDTO = buildVisitorDTO(visitorInfo);
        LoginHelper.setLoginVisitor(userDTO);

        return userDTO;
    }

    @Override
    public String getOpenIdByJsCode(String jsCode){
        if(StringUtils.isEmpty(jsCode)){
            throw new BaseException(-1,"请检查提交的code！");
        }

        String url = String.format(GlobalConst.OPENID_BASE_URL,appConfigs.getWechatAppId(),appConfigs.getWechatAppSecret(),jsCode,appConfigs.getWechatGrantType());
        log.info("begin request....url={}",url);

        String jsonBody = HttpUtil.createGet(url).execute().body();
        log.info("response....json={}",jsonBody);

        WechatOpenidResponse response = jsonService.jsonToObject(jsonBody,WechatOpenidResponse.class);

        Integer errorCode = response.getErrcode();

        if(!StringUtils.isEmpty(errorCode)){
            switch (errorCode){
                case GlobalConst.SYSTEM_BUSY:
                    throw new BaseException(errorCode,"系统繁忙,请稍后再尝试");
                case GlobalConst.INVALID_CODE:
                    throw new BaseException(errorCode,"临时code无效,请稍后再尝试");
                case GlobalConst.REQUEST_ACCOUNT_ERROR:
                    throw new BaseException(errorCode,"请求频率异常,请稍后再尝试");
                case GlobalConst.USER_DANGEROUS:
                    throw new BaseException(errorCode,"高风险等级用户,无法进入,请联系微信官方解决");
            }
        }

        return response.getOpenid();
    }

    @Override
    public void sendWechatTemplateMsg(WxTemplateMsgVO templateMsgVO) {
        String globalAccessToken = getGlobalAccessToken();
        //获取token失败记录日志
        if(StringUtils.isEmpty(globalAccessToken)){
            log.error("getGlobalAccessToken error...");
            return;
        }

        //得到请求url
        String url = String.format(GlobalConst.SEND_MESSAGE_TEMPLATE_URL,globalAccessToken);
        String jsonString = jsonService.objectToJson(templateMsgVO);
        String resultJson = HttpUtil.post(url, jsonString);

        Map<String,String> resultMap = jsonService.jsonToObject(resultJson,Map.class,String.class,String.class);

        //失败记录日志
        if(!"0".equals(resultMap.get("errcode"))){
            log.error("sendWechatTemplateMsg error,errcode={},msg={}",resultMap.get("errcode"),resultMap.get("errmsg"));
        }
    }

    @Override
    public String getGlobalAccessToken(){
        // 从缓存中获取token
        String cacheName = GlobalConst.WECHAT_GLOBAL_TOKEN;
        String wechatAccessToken = cacheService.getCache(cacheName, GlobalConst.WECHAT_GLOBAL_TOKEN_KEY, String.class);
        if (!StringUtils.isEmpty(wechatAccessToken)) {
            return wechatAccessToken;
        }

        //否则手动获取
        String url = String
                .format(GlobalConst.WX_ACCESS_TOKEN_URL, appConfigs.getWechatAppId(), appConfigs.getWechatAppSecret());
        HttpResponse response = HttpUtil.createGet(url).execute();
        if(RESPONSE_STATUS_SUCCESS.equals(response.getStatus())){
            String jsonResult = response.body();
            Map<String,String> resultMap = jsonService.jsonToObject(jsonResult,Map.class,String.class,String.class);
            String accessToken = resultMap.get(ACCESS_TOKEN_KEY);

            //把token加入缓存
            cacheService.put(cacheName,GlobalConst.WECHAT_GLOBAL_TOKEN_KEY,accessToken);

            return accessToken;
        }
        else{
            log.error("getGlobalAccessToken error,response={}",response);
        }

        return null;
    }

    @Override
    public UserDTO buildVisitorDTO(VisitorInfo visitorInfo){
        String timeNow = DateTimeUtil.getTimeNow();

        //根据openId建立token
        String token = LoginHelper.createTokenByVisitorOpenId(visitorInfo.getOpenId());

        //返回的用户信息耶带上token
        UserDTO dto = new UserDTO();
        dto.setId(visitorInfo.getId());
        dto.setLoginTime(timeNow);
        dto.setType(GlobalConst.USER_TYPE_VISITOR);
        dto.setTypeName(GlobalConst.GET_USERTYPE_NAME_MAP().get(GlobalConst.USER_TYPE_VISITOR));
        dto.setUsername(visitorInfo.getPhone());
        dto.setNickname(visitorInfo.getUsername());
        dto.setToken(token);

        return dto;
    }

    @Override
    public UserDTO buildUserDTO(User userInfo){

        return buildUserDTO(userInfo,null);
    }

    @Override
    public boolean getTel(String iphone){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //查询被访者以及安全员是否有这个电话的用户
        queryWrapper
                .eq("username",iphone)
                .and(a -> a
                        .eq("type",GlobalConst.USER_TYPE_INTERVIEWEE)
                        .or()
                        .eq("type",GlobalConst.USER_TYPE_SAFETY_OFFICER));

        long count = count(queryWrapper);

        return count > 0 ;
    }

    @Override
    public DaySettingBean selectMaxConfigTime() {
        String configValue = globalConfigService.getGlobalConfigByKey(GlobalConst.MAX_SELECT_TIME_KEY).getConfigValue();

        return jsonService.jsonToObject(configValue, DaySettingBean.class);
    }

    @Override
    public PageDTO<UserDetailDTO> adminSelectUserByCondition(AdminQueryVO adminQueryVO) {

        UserDTO loginUser = LoginHelper.getLoginUser();
        log.info("loginUser={}",loginUser);
        if(null == loginUser){
            throw new BaseException(-1,"登录信息异常！");
        }

        if(!GlobalConst.USER_TYPE_ADMIN.equals(loginUser.getType())){
            throw new BaseException(-1,"您不是管理员无法查询！");
        }

        //拿到原始user
        User loginUserDetailInfo = getById(loginUser.getId());

        //返回数据
        PageDTO<UserDetailDTO> ret = new PageDTO<>();
        ret.setPage(adminQueryVO.getPage());
        ret.setPageSize(adminQueryVO.getPageSize());

        //分页或者直接查询
        List<User> userList;
        if(!CheckParamUtils.isAnyParamNull(adminQueryVO.getPage(),adminQueryVO.getPageSize())){
            Page<User> page = new Page<>(adminQueryVO.getPage(), adminQueryVO.getPageSize());
            userList = userMapper.selectByCondition(page,adminQueryVO,loginUserDetailInfo);
            ret.setTotal(page.getTotal());
        }
        else{
            userList = userMapper.selectByCondition(adminQueryVO,loginUserDetailInfo);
            ret.setTotal(userList.size());
        }

        //没数据直接返回
        if(CollectionUtils.isEmpty(userList)){
            ret.setData(new ArrayList<>());
            ret.setTotal(0L);
            return ret;
        }

        //批量查询用户的最后一次登录时间
        List<Long> userIdList = userList.stream().map(User::getId).collect(Collectors.toList());
        List<LogRecord> logRecordList = logRecordMapper.selectLastLoginBatch(userIdList);

        //有数据组装DTO
        List<UserDetailDTO> detailDTOList = userList
                .stream()
                .map(user -> {
                    UserDetailDTO detailDTO = new UserDetailDTO();
                    BeanUtils.copyProperties(user, detailDTO);

                    //用户类型名称
                    detailDTO.setUserTypeName(GlobalConst.GET_USERTYPE_NAME_MAP().get(user.getType()));

                    //最后一次登录时间
                    logRecordList
                            .stream()
                            .filter(logRecord -> logRecord.getUserId().equals(user.getId()))
                            .findAny()
                            .ifPresent(lastLoginRecord -> detailDTO.setLastLoginTime(lastLoginRecord.getLogTime()));

                    return detailDTO;
                })
                .collect(Collectors.toList());

        ret.setData(detailDTOList);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrEditAccount(AdminUserVO adminQueryVO) {
        //默认pid为0的管理员可以操作其他管理员信息，删除或者修改其他管理员信息，其余管理员只能修改被访者与安全员与自己的信息
        UserDTO loginUser = LoginHelper.getLoginUser();

        if(null == loginUser){
            throw new BaseException(-1,"登录管理员信息异常！");
        }

        if(!GlobalConst.USER_TYPE_ADMIN.equals(loginUser.getType())){
            throw new BaseException(-1,"当前用户非管理员不能操作！");
        }

        if(adminQueryVO.getType() != null && !GlobalConst.ADMIN_USER_TYPE_LIST.contains(adminQueryVO.getType())){
            throw new BaseException(-1,"选择的用户类型异常！");
        }

        User loginAdminInfo = getById(loginUser.getId());

        //新增
        if(adminQueryVO.getId() == null){
            addAccount(adminQueryVO,loginAdminInfo);
        }
        //修改
        else{
            User oldUserInfo = getById(adminQueryVO.getId());

            //如果是修改用户，则判断修改的用户是否不是自己，如果不是自己，则判断自己是否能够修改
            if(adminQueryVO.getId() != null && !loginAdminInfo.getId().equals(adminQueryVO.getId())){
                if(!SUPPER_ADMIN_PID.equals(loginAdminInfo.getPid())
                        && GlobalConst.USER_TYPE_ADMIN.equals(oldUserInfo.getType())){
                    throw new BaseException(-1,"当前用户非超级管理员不能修改其他管理员用户！");
                }
            }
            editAccount(adminQueryVO,oldUserInfo);
        }

    }

    @Override
    @LoginCheck
    public boolean deleteAccount(Long userId) {
        if(null == userId){
            throw new JgException(ServiceCode.BAD_REQUEST);
        }

        User needDelUser = getById(userId);

        //判断要删除的用户是否已经有数据了，如果有有则不允许删除，直接统计申请记录表，被访人电话是自己的即可
        long contacts_phone = visitorApplyRecordService.count(new QueryWrapper<VisitorApplyRecord>()
                .eq("contacts_phone", needDelUser.getUsername()));

        if(contacts_phone > 0){
            throw new BaseException(-1,"当前删除用户已经存在关联数据无法删除！");
        }

        return removeById(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserDTO updateSelfInfo(EditUserVO vo) {
        if(vo == null || vo.getId() == null){
            throw new JgException(ServiceCode.BAD_REQUEST);
        }

        UserDTO loginUser = LoginHelper.getLoginUser();

        if(loginUser == null){
            throw new BaseException(-1,"登录信息异常！");
        }

        //查询原始user数据
        User user = getById(vo.getId());

        if(null == user){
            throw new BaseException(-1,"用户不存在！");
        }

        //更新,改用户名，则修改所有有关用户名的信息
        if(!user.getUsername().equals(vo.getUsername())){

            //更新用户名必要校验
            updateUserAccount(vo,user);

            //更改user的账号
            user.setUsername(vo.getUsername());
        }

        //更改昵称
        if(!StringUtils.isEmpty(vo.getNickname())){
            user.setNickname(vo.getNickname());
        }

        //更改头像
        if(!StringUtils.isEmpty(vo.getAvatar())){
            user.setAvatar(vo.getAvatar());
        }

        //更改密码
        if(!StringUtils.isEmpty(vo.getPassword())){
            String encryptPassword = MD5.encrypt(vo.getPassword());
            user.setPassword(encryptPassword);
        }

        //更新
        user.updateById();

        //返回新的user
        UserDTO userDTO = buildUserDTO(user,loginUser.getToken());

        LoginHelper.setLoginUser(userDTO);

        return userDTO;
    }

    /**
     * 考虑到这个动作不可能高并发，所以加锁，同步方法，保证每次上传的在成员变量里面不会混乱
     * @param file 文件
     * @return 是否成功
     */
    @Override
    @LoginCheck
    public synchronized String uploadBatchUser(MultipartFile file){
        if(file == null){
            throw new BaseException(-1,"请选择上传的模板！");
        }

        //先清空每次的数据
        SINGLE_REQUEST_DATA.clear();

        try {
            ExcelReader excelReader = EasyExcel.read(file.getInputStream(), UploadUserBean.class,new BatchUploadUserExcelListener(this)).build();
            ReadSheet sheet1 = EasyExcel.readSheet(0,"被访者").build();
            ReadSheet sheet2 = EasyExcel.readSheet(1,"安全员").build();
            ReadSheet sheet3 = EasyExcel.readSheet(2,"管理员").build();
            excelReader.read(sheet1,sheet2,sheet3);

            List<UploadUserBeanInfo> errorRowList = addNewUser();

            if(errorRowList != null && errorRowList.size() > 0){
                return getErrorMsg(errorRowList);
            }
        }
        //异常返回
        catch (IOException e) {
            log.error("uploadBatchUser error",e);
        }
        //每次都会清空
        finally {
            SINGLE_REQUEST_DATA.clear();
        }

        return "success";
    }

    @Override
    public void addSingleRequestData(UploadUserBeanInfo data) {
        SINGLE_REQUEST_DATA.add(data);
    }

    private List<UploadUserBeanInfo> addNewUser(){
        //读取完后得到数据
        if(CollectionUtils.isEmpty(SINGLE_REQUEST_DATA)){
            return new ArrayList<>();
        }

        UserDTO adminUser = LoginHelper.getLoginUser();

        if (adminUser == null){
            throw new BaseException(-1,"管理员登录信息异常!");
        }

        List<String> phoneList = SINGLE_REQUEST_DATA
                .stream()
                .map(UploadUserBean::getPhone)
                .distinct()
                .collect(Collectors.toList());

        Map<String, Integer> phoneCountMap = userMapper
                .batchSelectPhoneCount(phoneList)
                .stream()
                .collect(Collectors.toMap(PhoneCountBean::getPhone, PhoneCountBean::getCount));

        List<User> newUser = SINGLE_REQUEST_DATA
                .stream()
                .filter(data -> phoneCountMap.get(data.getPhone()) == null || phoneCountMap.get(data.getPhone()) == 0)
                .map(data -> {
                    User user = new User();
                    user.setUsername(data.getPhone());
                    user.setNickname(data.getUsername());
                    user.setGmtCreate(DateTimeUtil.getTimeNow());
                    user.setPid(adminUser.getId());
                    user.setGmtModified(DateTimeUtil.getTimeNow());
                    user.setPassword(MD5.encrypt(GlobalConst.DEFAULT_PASSWORD));
                    user.setType(data.getSheetNo());
                    return user;
                })
                .collect(Collectors.toList());

        if(!CollectionUtils.isEmpty(newUser)){
            List<List<User>> partition = ListUtils.partition(newUser, 100);
            partition.forEach(batchData -> userMapper.saveBatch(batchData));
        }

        //返回已经存在了的数据
        return SINGLE_REQUEST_DATA
                .stream()
                .filter(data -> phoneCountMap.get(data.getPhone()) != null && phoneCountMap.get(data.getPhone()) > 0)
                .collect(Collectors.toList());
    }

    private String getErrorMsg(List<UploadUserBeanInfo> errorRowList) {
        StringBuilder errorMsg = new StringBuilder();

        Map<String, List<UploadUserBeanInfo>> sheetMap = errorRowList.stream().collect(Collectors.groupingBy(UploadUserBeanInfo::getSheet));

        for (Map.Entry<String, List<UploadUserBeanInfo>> entry : sheetMap.entrySet()) {
            StringBuilder sheetName = new StringBuilder("Sheet页==>" + entry.getKey() + "==>");
            for (UploadUserBeanInfo beanInfo : entry.getValue()) {
                sheetName.append("第").append(beanInfo.getRow()).append("行,");
            }
            errorMsg.append(sheetName);
        }

        errorMsg.append("手机号已被使用,无法添加！");

        return errorMsg.toString();
    }

    public UserDTO buildUserDTO(User userInfo,String token){
        //返回的用户信息耶带上token
        UserDTO dto = new UserDTO();

        //生成雪花id token 作用于token续期
        String snakeToken = IdWorker.getIdStr();
        dto.setSnakeToken(snakeToken);

        //登录时间
        dto.setLoginTime(DateTimeUtil.getTimeNow());
        //登录过期时间
        dto.setExpireTime(DateTimeUtil.getTimeStrByLong(System.currentTimeMillis() + 30 * 60 * 1000));

        //如果没有指定token，需要根据雪花token生成认证token
        if(StringUtils.isEmpty(token)){
            token = LoginHelper.createTokenBySnakeToken(snakeToken);
        }

        dto.setId(userInfo.getId());
        dto.setLoginTime(DateTimeUtil.getTimeNow());
        dto.setType(userInfo.getType());
        dto.setTypeName(GlobalConst.GET_USERTYPE_NAME_MAP().get(userInfo.getType()));
        dto.setUsername(userInfo.getUsername());
        dto.setNickname(userInfo.getNickname());
        dto.setToken(token);
        dto.setAvatar(userInfo.getAvatar());

        //上次登录时间，如果为空第一次登录
        LogRecord logRecordOld = logRecordMapper.selectLastLogin(userInfo.getId());

        dto.setOldLoginTime(logRecordOld == null ? DateTimeUtil.getTimeNow() : logRecordOld.getLogTime());

        return dto;
    }

    private User checkAndGetUser(UserLoginVO userVO){
        //通过手机号查询该账号
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username",userVO.getUsername());

        long count = count(queryWrapper);
        if(count < 1){
            throw new BaseException(-1,"没有找到该账号!");
        }

        //MD5加密后，对比数据库加密后的密码，判断密码是否正确
        String encryptPassword = MD5.encrypt(userVO.getPassword());

        //再通过密码查询此账号
        queryWrapper.eq("password",encryptPassword);
        User userInfo = getOne(queryWrapper);
        if(userInfo == null){
            throw new BaseException(-1,"密码错误!");
        }

        return userInfo;
    }

    public void updateUserAccount(EditUserVO vo,User oldUser){
        if(GlobalConst.ADMIN_USER.equals(oldUser.getUsername())){
            throw new BaseException(-1,"超级管理员不能修改用户名！");
        }

        //校验手机是否被其他人使用
        AdminUserVO condition = new AdminUserVO();
        BeanUtils.copyProperties(vo,condition);
        condition.setType(oldUser.getType());
        long sameUserCount = getSameUserCount(condition);
        if(sameUserCount > 0){
            throw new BaseException(-1,"该用户类型下存在相同的手机号！");
        }

        //所有之前的访客申请记录都要更新被访者电话
        UpdateWrapper<VisitorApplyRecord> updateWrapper = new UpdateWrapper<VisitorApplyRecord>()
                .eq("contacts_phone", oldUser.getUsername()).set("contacts_phone", vo.getUsername());
        visitorApplyRecordService.update(updateWrapper);
    }

    public void addAccount(AdminUserVO adminQueryVO,User loginAdminInfo){
        long count = getSameUserCount(adminQueryVO);
        if(count > 0){
            throw new BaseException(-1,"该手机号已被使用无法添加！");
        }

        User user = new User();
        user.setGmtCreate(DateTimeUtil.getTimeNow());
        user.setGmtModified(DateTimeUtil.getTimeNow());
        user.setPid(loginAdminInfo.getId());
        user.setUsername(adminQueryVO.getUsername());
        user.setNickname(adminQueryVO.getNickname());
        user.setType(adminQueryVO.getType());
        user.setAvatar(adminQueryVO.getAvatar());
        user.setPassword(MD5.encrypt(adminQueryVO.getPassword()));
        user.insert();
    }

    public void editAccount(AdminUserVO adminQueryVO,User oldUserInfo){
        //如果修改后的手机和修改前的不同，则查询是否手机已经被使用过了
        if(!oldUserInfo.getUsername().equals(adminQueryVO.getUsername()) || !oldUserInfo.getType().equals(adminQueryVO.getType())){
            long count = getSameUserCount(adminQueryVO);
            if(count > 0){
                throw new BaseException(-1,"该手机号已被使用无法修改！");
            }
        }

        oldUserInfo.setGmtModified(DateTimeUtil.getTimeNow());
        //昵称
        if(!StringUtils.isEmpty(adminQueryVO.getNickname())){
            oldUserInfo.setNickname(adminQueryVO.getNickname());
        }
        //密码
        if(!StringUtils.isEmpty(adminQueryVO.getPassword()) && !adminQueryVO.getPassword().equals(oldUserInfo.getPassword())){
            if(GlobalConst.ADMIN_USER.equals(oldUserInfo.getUsername())){
                throw new BaseException(-1,"admin用户不允许修改密码！");
            }
            oldUserInfo.setPassword(MD5.encrypt(adminQueryVO.getNickname()));
        }
        //用户名（手机）
        if(!StringUtils.isEmpty(adminQueryVO.getUsername()) && !adminQueryVO.getUsername().equals(oldUserInfo.getUsername())){
            if(GlobalConst.ADMIN_USER.equals(oldUserInfo.getUsername())){
                throw new BaseException(-1,"admin用户不允许修改账号！");
            }
            //更新用户名必要校验
            updateUserAccount(adminQueryVO,oldUserInfo);

            oldUserInfo.setUsername(adminQueryVO.getUsername());
        }
        //账户类型
        boolean isTypeChange = false;
        if(null != adminQueryVO.getType() && !adminQueryVO.getType().equals(oldUserInfo.getType())){
            if(GlobalConst.ADMIN_USER.equals(oldUserInfo.getUsername())){
                throw new BaseException(-1,"admin用户不允许修改角色！");
            }
            oldUserInfo.setType(adminQueryVO.getType());
            isTypeChange = true;
        }
        //头像
        if(!StringUtils.isEmpty(adminQueryVO.getAvatar())){
            oldUserInfo.setAvatar(adminQueryVO.getAvatar());
        }

        oldUserInfo.updateById();

        //如果角色更改了，并且登录用户的缓存内有此用户，则更改缓存的用户角色
        if(isTypeChange){
            Map<String, Object> allCache = cacheService.getAllCache(GlobalConst.LOGIN_ADMIN);

            String allCacheJson = jsonService.objectToJson(allCache);

            Map<String,UserDTO> loginUserMap = jsonService.jsonToObject(allCacheJson,Map.class,String.class,UserDTO.class);

            loginUserMap
                    .entrySet()
                    .stream()
                    .filter(entry -> entry.getValue().getId().equals(oldUserInfo.getId()))
                    .forEach(entry -> {
                        UserDTO userDTO = entry.getValue();
                        userDTO.setType(oldUserInfo.getType());
                        cacheService.put(GlobalConst.LOGIN_ADMIN,entry.getKey(),userDTO);
                    });
        }
    }

    private long getSameUserCount(AdminUserVO adminQueryVO){
        //新增时，判断手机号是否已经有用户使用过了
        QueryWrapper<User> queryCondition = new QueryWrapper<User>().eq("username", adminQueryVO.getUsername());

        if(adminQueryVO.getId() != null){
            queryCondition.ne("id",adminQueryVO.getId());
        }

        return count(queryCondition);
    }

}




